package cn.jdw.shop;

import cn.jdw.shop.product.entity.Commodity;
import cn.jdw.shop.product.service.ICommodityService;
import cn.test.TimeUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author ListJiang
 * @since 2021/9/22 10:52
 * description 自定义延迟执行
 */
@Component
public class CustomRunner implements ApplicationRunner {

    @Autowired
    JavaMailSender javaMailSender;
    @Autowired
    ICommodityService iCommodityService;
    @Autowired
    ThreadPoolTaskScheduler taskScheduler;

    @Value("${spring.mail.username}")
    String username;
    @Value("${open}")
    boolean open;
    @Value("#{'${mails}'.split(',')}")
    String[] mails;
    @Value("${url}")
    String url;


    @Override
    public void run(ApplicationArguments args) {
        while (open) {
            System.out.println("请求地址：" + url);
            Document document = null;
            try {
                document = Jsoup.connect(url)
                        .userAgent("Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.0").get();
                Elements scripts = document.select("script");
                List<Commodity> commodities = iCommodityService.list();
                List<String> ids = commodities.stream().map(Commodity::getId).toList();

                Map<String, Commodity> map = commodities.stream().collect(Collectors.toMap(Commodity::getId, t -> t));
                List<Commodity> results = scripts.stream()
                        .filter(s -> s.data().contains("window.REFURB_GRID_BOOTSTRAP"))
                        .flatMap(s -> {
                            // 获取数据
                            String replace = s.data().replace("window.REFURB_GRID_BOOTSTRAP = ", "")
                                    .replace("\n", "").trim();
                            String substring = replace.substring(0, replace.length() - 1);
                            JSONObject parse = (JSONObject) JSONObject.parse(substring);
                            JSONArray title = parse.getJSONArray("tiles");
                            return title.stream();
                        })
                        .map(o -> (JSONObject) o)
                        .filter(jsonObject -> {
                            // 配置信息筛选
                            JSONObject json1 = jsonObject.getJSONObject("filters").getJSONObject("dimensions");
                            // 固态
                            boolean bool1 = Arrays.asList("1tb", "512gb").contains(json1.getString("dimensionCapacity"
                            ));
                            // 内存
                            boolean bool2 = Arrays.asList("16gb", "32gb").contains(json1.getString("tsMemorySize"));
                            // 出场年限
                            boolean bool3 = Arrays.asList("2019", "2020", "2021")
                                    .contains(json1.getString("dimensionRelYear"));
                            // 价格，
                            Float aFloat = jsonObject.getJSONObject("price").getJSONObject("currentPrice").getFloat(
                                    "raw_amount");
                            boolean bool4 = aFloat > 5000L && aFloat < 16000L;
                            return bool1 && bool2 && bool3 && bool4;
//                        return true;
                        })
                        .map(json -> {
                            // 构建短信需要的json
                            Commodity commodity = new Commodity();
                            JSONObject dimensions = json.getJSONObject("filters").getJSONObject("dimensions");
                            commodity.setTsmemorySize(dimensions.getString("tsMemorySize"));
                            commodity.setDimensionCapacity(dimensions.getString("dimensionCapacity"));
                            commodity.setDimensionScreenSize(dimensions.getString("tsMemorySize"));
                            commodity.setVersion(dimensions.getString("refurbClearModel") + dimensions.getString(
                                    "dimensionRelYear"));
                            commodity.setDimensionColor(dimensions.getString("dimensionColor"));
                            commodity.setRemark(json.getString("title"));
                            commodity.setPrice(json.getJSONObject("price").getJSONObject("currentPrice").getFloat(
                                    "raw_amount"));
                            commodity.generateId();
                            return commodity;
                        }).toList();
                System.out.println("======================================");
                // 构建新的需要入库的数据
                // 筛选出降价产品
                Map<String, Commodity> save = new HashMap<>();
                List<Commodity> collect = results.stream()
                        .filter(t -> {
                            if (map.containsKey(t.getId()) && map.get(t.getId()).getPrice() > t.getPrice()) {
                                // 该方案能解决重复id，但是价格不同
                                // if(!save.containsKey(t.getId())||(save.containsKey(t.getId())&&save.get(t.getId())
                                // .getPrice()>t.getPrice())){
                                //     save.put(t.getId(), t);
                                // }
                                return map.get(t.getId()).getPrice() > t.getPrice();
                            } else {
                                map.put(t.getId(), t);
                                return false;
                            }
                        })
                        .collect(Collectors.toList());
                // 更新数据库产品信息
                iCommodityService.saveOrUpdateBatch(collect);
                // iCommodityService.saveOrUpdateBatch(save.entrySet().stream().map(Map.Entry::getValue).toList());
                if (collect.size() > 0) {
                    String text = "";
                    String mailText = """
                            版本信息：%s
                            内存：%s\t磁盘：%s
                            原价：%s元\t现价：%s元
                            降价：%s元\n
                            """;
                    SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
                    // 发件人，这里的值必须是配置的发送邮箱账号的可用账号名，例如qq邮箱可以配置多个账号，这里是其中任意一个即可
                    simpleMailMessage.setFrom(username);
                    // 收件人
                    simpleMailMessage.setTo(mails);
                    // 邮件主题
                    simpleMailMessage.setSubject("有产品降价啦");
                    // 邮件内容
                    for (Commodity a : collect) {
                        Commodity b = map.get(a.getId());
                        String formatted = mailText.formatted(a.getRemark(), a.getTsmemorySize(),
                                a.getDimensionCapacity(),
                                b.getPrice(), a.getPrice(), b.getPrice() - a.getPrice());
                        System.out.println(formatted);
                        text += formatted;
                    }
                    simpleMailMessage.setText(text);
                    javaMailSender.send(simpleMailMessage);
                }
                System.out.println("\n\n\n" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd " +
                        "hh:mm:ss")));
                TimeUtils.sleep(4);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}